package org.ciallo.easytokencore.context;

import io.netty.util.concurrent.FastThreadLocal;
import org.ciallo.easytokencore.context.model.EasyCookie;
import org.ciallo.easytokencore.context.model.EasyRequest;
import org.ciallo.easytokencore.context.model.EasyResponse;
import org.ciallo.easytokencore.context.model.EasyToken;

/**
 * Easy-Token 上下文线程持有类
 *
 * <p>核心功能：</p>
 * <ul>
 *   <li>基于FastThreadLocal实现高性能线程安全上下文管理</li>
 *   <li>提供全局访问当前请求上下文的统一入口</li>
 *   <li>自动清理上下文防止内存泄漏</li>
 *   <li>支持WebFlux等异步编程模型</li>
 * </ul>
 *
 * <p>技术实现：</p>
 * <ul>
 *   <li>使用FastThreadLocal替代普通ThreadLocal</li>
 *   <li>内部使用索引而非哈希表存储，减少内存占用</li>
 *   <li>自动清除机制避免线程池场景的内存泄漏</li>
 * </ul>
 *
 * <p>主要方法：</p>
 * <ul>
 *   <li>setContext(): 绑定当前线程的请求上下文</li>
 *   <li>getContext(): 获取当前线程的请求上下文</li>
 *   <li>clear(): 清理当前线程的上下文</li>
 *   <li>getRequest()/getResponse(): 便捷获取请求/响应对象</li>
 * </ul>
 *
 * <p>使用示例：</p>
 * <pre>
 * {@code
 * // 1. 拦截器中设置上下文
 * EasyContextHolder.setContext(cookie, request, response, token);
 *
 * // 2. 控制器中获取请求参数
 * String userId = EasyContextHolder.getToken().getPayload("userId");
 *
 * // 3. 服务层设置响应头
 * EasyContextHolder.getResponse().addHeader("X-Trace-Id", traceId);
 *
 * // 4. 过滤器清理上下文(必须!)
 * EasyContextHolder.clear();
 * }
 * </pre>
 *
 * <p>注意事项：</p>
 * <ul>
 *   <li>必须在请求结束时调用clear()方法，特别是在线程池场景</li>
 *   <li>异步任务中需要手动传递上下文，不能直接使用</li>
 *   <li>FastThreadLocal的性能优势在高并发场景更明显</li>
 * </ul>
 *
 * @Description: Easy-Token 上下文线程持有类
 * @Author: Jukomu
 * @Package: org.ciallo.easytokencore.context
 * @Project: easy-token-demo
 * @Version: 1.1.0
 * @name: EasyContextHolder
 * @Date: 2025-05-17
 * @Filename: EasyContextHolder
 * @see EasyContext
 * @see <a href="https://netty.io/wiki/thread-local-performance.html">FastThreadLocal性能说明</a>
 */
public class EasyContextHolder {
    // 使用 ThreadLocal 保存当前线程的请求上下文
    private static final FastThreadLocal<EasyContext> contextHolder = new FastThreadLocal<>();

    /**
     * 设置当前请求的上下文
     */
    public static void setContext(EasyCookie cookie, EasyRequest request, EasyResponse response, EasyToken token) {
        EasyContext context = new EasyContext(cookie, request, response, token);
        contextHolder.set(context);
    }

    /**
     * 获取当前请求的上下文
     */
    public static EasyContext getContext() {
        return contextHolder.get();
    }

    /**
     * 清理上下文（防止内存泄漏）
     */
    public static void clear() {
        contextHolder.remove();
    }

    /**
     * 获取当前线程的 EasyRequest 对象
     *
     * @return 当前线程的 EasyRequest 对象
     */
    public static EasyRequest getRequest() {
        return contextHolder.get().getRequest();
    }

    /**
     * 获取响应对象
     *
     * @return EasyResponse对象，包含了响应的数据
     */
    public static EasyResponse getResponse() {
        return contextHolder.get().getResponse();
    }

    /**
     * 获取上下文token对象
     *
     * @return EasyToken，包含了上下文token
     */
    public static EasyToken getToken() {
        return contextHolder.get().getToken();
    }
}
